package com.vcolco.scanner.config;

import com.alibaba.fastjson.JSON;
import com.vcolco.scanner.entity.AccessUserInfo;
import com.vcolco.scanner.entity.UserInfo;
import com.vcolco.scanner.entity.UserOrgId;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Optional;

/**
 * @author lei
 * @create 2021-08-16 09:51
 * @desc 操作用户拦截器
 **/
@Slf4j
public class UserInterceptorConfig implements HandlerInterceptor {

    /**
     * 使用InheritableThreadLocal 该类可以由子线程获取到父线程的数据
     * 用以解决使用并行流时 Mp自动填充获取不到操作人
     */
    public static final ThreadLocal<UserInfo> USER_INFO = new InheritableThreadLocal<>();
    public static final ThreadLocal<AccessUserInfo> ACCESS_USER_INFO = new InheritableThreadLocal<>();
    public static final String ACCESS_USER_INFO_HEADER = "access-user-info";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        AccessUserInfo accessUserInfo = JSON.parseObject(request.getHeader(ACCESS_USER_INFO_HEADER), AccessUserInfo.class);
        ACCESS_USER_INFO.set(accessUserInfo);
        log.debug("InterceptorConfig::preHandle {} {}", accessUserInfo, request.getRequestURI());
        UserInfo userInfo = Optional.ofNullable(accessUserInfo)
                .map(curUser -> UserInfo.builder().userId(curUser.getUserId())
                        .userIp(curUser.getUserIp())
                        .orgId(Optional.ofNullable(curUser.getExtension())
                                .map(extension -> JSON.parseObject(extension, UserOrgId.class)).map(UserOrgId::getOrgId).orElse(null))
                        .build()
                ).orElseGet(() -> UserInfo.builder().build());
        USER_INFO.set(userInfo);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        ACCESS_USER_INFO.remove();
        USER_INFO.remove();
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // Do nothing
    }

    public static UserInfo getCurrentUser() {
        return Optional.of(UserInterceptorConfig.USER_INFO)
                .map(ThreadLocal::get)
                .filter(userInfo -> userInfo.getUserId() != null)
                .orElse(null);
    }

    public static String getCurrentUserId() {
        return Optional.ofNullable(UserInterceptorConfig.getCurrentUser()).map(UserInfo::getUserId).orElse(null);
    }

    public static String getCurrentUserIdAndThrow() {
        return Optional.ofNullable(UserInterceptorConfig.getCurrentUser()).map(UserInfo::getUserId).orElseThrow(() -> new RuntimeException("未获取到用户ID"));
    }

    public static Integer getCurrentUserOrgIdAndThrow() {
        return Optional.ofNullable(UserInterceptorConfig.getCurrentUser()).map(UserInfo::getOrgId).orElseThrow(() -> new RuntimeException("未获取到用户机构信息"));
    }
}
